
#include "GeosphereFace.h"

#include <iostream>
using namespace std;

/*--------------------------------------------------------------------*/
GeosphereFace::GeosphereFace() {
	isDivided = false;
}

/*--------------------------------------------------------------------*/
void GeosphereFace::setVerts(Vec3f a, Vec3f b, Vec3f c) {
	verts = new GeosphereVert*[3];
	verts[0] = new GeosphereVert();
	verts[1] = new GeosphereVert();
	verts[2] = new GeosphereVert();
	
	verts[0]->vert = a;
	verts[1]->vert = b;
	verts[2]->vert = c;

	calcFaceNorm();
}

/*--------------------------------------------------------------------*/
void GeosphereFace::calcFaceNorm() {

	verts[0]->calcUnit();
	verts[1]->calcUnit();
	verts[2]->calcUnit();

	verts[0]->calcNorm();
	verts[1]->calcNorm();
	verts[2]->calcNorm();

	Vec3f AC = verts[2]->vert - verts[0]->vert;
	Vec3f AB = verts[1]->vert - verts[0]->vert;
	faceNorm = AC.crossedWith(AB);
	faceNorm.normalize();

	// Keep all normals facing outward
	if ( verts[0]->unit * faceNorm < 0 ) { faceNorm = -faceNorm; }
}


/*--------------------------------------------------------------------*/
void GeosphereFace::calcTexCoords(float r) {

	Vec3f mid = verts[0]->unit + verts[1]->unit + verts[2]->unit;
	mid.normalize();

	verts[0]->calcTexUV(mid);
	verts[1]->calcTexUV(mid);
	verts[2]->calcTexUV(mid);
}

/*--------------------------------------------------------------------*/
void GeosphereFace::doSplit(float r, int levelsLeft) {

	if ( --levelsLeft < 0 ) { return; }

	isDivided = true;

	Vec3f ab = verts[0]->vert + verts[1]->vert;
	Vec3f bc = verts[1]->vert + verts[2]->vert;
	Vec3f ca = verts[2]->vert + verts[0]->vert;

	ab.normalizeToLength(r);
	bc.normalizeToLength(r);
	ca.normalizeToLength(r);

	faces = new GeosphereFace[4];
	faces[0].setVerts( verts[0]->vert, ab, ca );
	faces[1].setVerts( verts[1]->vert, bc, ab );
	faces[2].setVerts( verts[2]->vert, ca, bc );
	faces[3].setVerts( ab, bc, ca );

	for ( int i = 0 ; i < 4 ; i++ ) { 
		faces[i].calcTexCoords(r);
		faces[i].doSplit(r, levelsLeft);
	}
}

/*--------------------------------------------------------------------*/
void GeosphereFace::collectFaces(list<GeosphereFace*>& faceList) {
	if ( !isDivided ) { return; }
	for ( int i = 0 ; i < 4 ; i++ ) {
		faceList.push_back(&faces[i]);
		faces[i].collectFaces(faceList);
	}
}

/*--------------------------------------------------------------------*/
GeosphereVert** GeosphereFace::getVerts() { return verts; }
bool GeosphereFace::getIsDivided() { return isDivided; }
const Vec3f* GeosphereFace::getFaceNorm() { return &faceNorm; }
GeosphereFace* GeosphereFace::getFace(int i) { return &faces[i]; }
const GeosphereVert* GeosphereFace::getVert(int i) { return verts[i]; }
